/***************************************************************************
 *   Copyright © 2010 by Nikolay Kornaev                                   *
 *   n.kornaev@gmail.com                                                   *
 *                                                                         *
 *                    This file is part of neuma.                          *
 *                                                                         *
 *   neuma is free software; you can redistribute it and/or modify it      *
 *   under the terms of the GNU General Public License as published by     *
 *   the Free Software Foundation; either version 3 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   neuma is distributed in the hope that it will be useful,              *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, see <http://www.gnu.org/licenses/>   *
 ***************************************************************************/

#include "sp_plain.h"
#include "SyntaxHighlighter.h"

namespace Neuma
{
  bool sp_plain::fromText(const QString &source, NeumasData *data)
  {
    d = data;
    QString in = source;
    in.prepend("\n");
    in.append("\n");
    toBeContinued = false;
    d->clear();

    QRegExp rxNeumasLine = QRegExp("\\n" + N_LINE_NEUMAS + "\\s*(.*)\\n", Qt::CaseInsensitive,
        QRegExp::RegExp2);
    rxNeumasLine.setMinimal(true);
    QRegExp rxSylbesLine = QRegExp("\\n" + N_LINE_SYLLABES + "\\s*(.*)\\n", Qt::CaseInsensitive,
        QRegExp::RegExp2);
    rxSylbesLine.setMinimal(true);

    QString neumasLine;
    QString sylbesLine;

    int pos = 0;
    while ((pos = rxNeumasLine.indexIn(in, pos)) != -1)
    {
      neumasLine = rxNeumasLine.cap(1);
      pos += rxNeumasLine.matchedLength();
      pos -= 2;
      if ((pos = rxSylbesLine.indexIn(in, pos)) == -1)
        break;
      sylbesLine = rxSylbesLine.cap(1);
      pos += rxSylbesLine.matchedLength();
      pos -= 2;
      parseLine(neumasLine.trimmed(), sylbesLine.trimmed());
    }

    data = d;
    toBeContinued = false;
    return true;
  }

  int sp_plain::parseLine(const QString & neumasLine, const QString & sylbesLine)
  {
    QStringList neumas = neumasLine.split(QRegExp("\\s+"));
    QStringList sylbes = sylbesLine.split(QRegExp("\\s+"));
    int m = qMin(neumas.size(), sylbes.size());
    if (m)
      for (int i = 0; i < m; ++i)
      {
        QString n = neumas[i];
        QString s = sylbes[i];

        // вставка нового перевода строки
        if (n == N_INSERT_NEW_LINE && s == N_INSERT_NEW_LINE)
        {
          d->append(new NSPair());
          continue;
        }

        // удаление существующего перевода строки
        if (n == N_REMOVE_NEW_LINE && s == N_REMOVE_NEW_LINE)
        {
          toBeContinued = true;
          continue;
        }
        d->append(new NSPair(neumas[i], sylbes[i]));
      }
    if (!toBeContinued)
      d->append(new NSPair());
    toBeContinued = false;
    return 0;
  }

  bool sp_plain::toText(const NeumasData *data, QString &out)
  {
    QString nt = "\n"; /// конец строки невм
    QString st = "\n\n"; /// конец строки слогов
    QString ci = "\n"; /// начало строки комментариев
    QString ct = "\n\n"; /// конец строки комментария

    QString _out;
    QString outN, outS;
    for (int i = 0; i < data->size(); ++i)
    {
      NSPair *pair = data->at(i);
      if (pair->isNewLine())
      {
        _out.append(N_LINE_NEUMAS + "\t");
        _out.append(outN.trimmed());
        _out.append(nt);
        _out.append(N_LINE_SYLLABES + "\t");
        _out.append(outS.trimmed());
        _out.append(st);
        outN.clear();
        outS.clear();
      }
      else if (pair->isComment())
      {
        _out.append(ci);
        _out.append(pair->getComment());
        _out.append(ct);
      }
      else
      {
        outN.append(pair->getNeuma());
        outN.append(N_BLOCK_SEPARATOR);
        outS.append(pair->getSyllabe());
        outS.append(N_BLOCK_SEPARATOR);
      }
    }
    out = _out;
    return true;
  }

  QSyntaxHighlighter * sp_plain::syntaxHighLighter(QTextDocument *doc)
  {
    QSyntaxHighlighter *sh = new NeumaSyntaxHighlighter(doc);
    return sh;
  }
}

Q_EXPORT_PLUGIN2(sp_plain, Neuma::sp_plain)
